using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Threading;


namespace GameXNA_Master
{

    public struct gameInfoState
    {
        public static bool pause = true;
        public static bool some_To_Loading = false;
        public static bool Start_new_Level = false;
        public static bool pause_from_game = false;
        public static bool game_over = false;
    }

    class Camera
    {
        //float rotationSpeed = 0.05f;
        //float forwardSpeed = 9f;
        float viewAngle = MathHelper.PiOver4;
        
        float nearClip = 1.0f;
        float farClip = 50000.0f;
        //float mouseSensitive = 0.01f;

        Vector3 transformedReference;

        public Vector3 cameraLookAt;
        public Matrix rotMatrix;
        public float avatarYaw;
        public float avatarPitch;
        public float aspectRatio; // dovrebbe seere fornito da RenderingData
        public Vector3 position;
        public Matrix view;
        public Matrix proj;
        public Matrix world = Matrix.Identity;


        public void setProjMatrix()
        {
            proj = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip);
        }


        public Matrix rotationY;
        public Vector3 sideMove;
        GamePadState gamepadState;
        public void setCamera(RenderingData rendering_data,SettingsData settingsData, float elapsedSec)
        {
            if (settingsData.useJoystic)
            {
                gamepadState= GamePad.GetState(PlayerIndex.One);
                avatarPitch += (float)(gamepadState.ThumbSticks.Right.Y) * elapsedSec;
                avatarYaw -= (float)(gamepadState.ThumbSticks.Right.X ) * elapsedSec;
                Console.WriteLine(""+gamepadState.ThumbSticks.Right);
            }
            else
            {
                MouseState mouseState = Mouse.GetState();

                avatarPitch += (float)(mouseState.Y - rendering_data.screenHeight / 2) * elapsedSec * 0.5f;
                avatarYaw -= (float)(mouseState.X - rendering_data.screenWidth / 2) * elapsedSec * 0.5f;

                Mouse.SetPosition(rendering_data.screenWidth / 2, rendering_data.screenHeight / 2);
            }

            rotationY = Matrix.CreateRotationY(avatarYaw);
            sideMove = Vector3.Cross(Vector3.Up, rotationY.Forward);

            avatarPitch = MathHelper.Clamp(avatarPitch, MathHelper.ToRadians(-60), MathHelper.ToRadians(5));
            avatarYaw = MathHelper.Clamp(avatarYaw, MathHelper.ToRadians(-60), MathHelper.ToRadians(60));

            rotMatrix = Matrix.CreateFromYawPitchRoll(avatarYaw, avatarPitch,0);
            transformedReference = Vector3.Transform(Vector3.UnitZ, rotMatrix);

            cameraLookAt = position + transformedReference;

            view = Matrix.CreateLookAt(position, cameraLookAt, Vector3.Up);
            
           
            //Console.WriteLine(cameraLookAt);
        }
    }

    class RenderingData
    {
        public int screenHeight;
        public int screenWidth;
        public float aspectRatio;
        public Vector2 aimDim;
        public List<UInt32> screenHeightResolutions = new List<UInt32>();
        public List<UInt32> screenWidthtResolutions = new List<UInt32>();

    }

    class Floor
    {

        public VertexPositionNormalTexture[] Vertices;
        public short[] Indexes;
        Vector3 Origin;
        Vector3 Normal;
        Vector3 Up;
        Vector3 Left;
        Vector3 upperCenter;
        Vector3 upperLeft;
        Vector3 upperRight;
        Vector3 lowerLeft;
        Vector3 lowerRight;

        public float floorHeight;

        public void Quad(Vector3 origin, Vector3 normal, Vector3 up, float width, float height)
        {
            Vertices = new VertexPositionNormalTexture[4];
            Indexes = new short[6];

            Origin = origin;
            Normal = normal;
            Up = up;

            floorHeight = Origin.Y;

            Left = Vector3.Cross(normal, Up);
            upperCenter = (Up * height / 2) + origin;
            upperLeft = upperCenter + (Left * width / 2);
            upperRight = upperCenter - (Left * width / 2);
            lowerLeft = upperLeft - (Up * height);
            lowerRight = upperRight - (Up * height);

            FillVertices();
        }

        Vector2 textureUpperLeft;
        Vector2 textureUpperRight;
        Vector2 textureLowerLeft;
        Vector2 textureLowerRight;

        float fitText = 3f;

        /*
         * Assegna le coordinate UV della texture in un range da (0,0) a (1,1) in modo che la texture stia nel quadrato 
         */
        public void FillVertices()
        {
            textureUpperLeft = new Vector2(0f, 0f);
            textureUpperRight = new Vector2(fitText, 0f);
            textureLowerLeft = new Vector2(0f, fitText);
            textureLowerRight = new Vector2(fitText, fitText);

            // Assegno a tutti i vertici la stessa normale
            for (int i = 0; i < Vertices.Length; i++)
            {
                Vertices[i].Normal = Normal;
            }

            //Assegno ai vertici la posizione e le coordinate delle texture
            Vertices[0].Position = lowerLeft;
            Vertices[0].TextureCoordinate = textureLowerLeft;
            Vertices[1].Position = upperLeft;
            Vertices[1].TextureCoordinate = textureUpperLeft;
            Vertices[2].Position = lowerRight;
            Vertices[2].TextureCoordinate = textureLowerRight;
            Vertices[3].Position = upperRight;
            Vertices[3].TextureCoordinate = textureUpperRight;

            //Inserisco nell' indexes i dei valori che corrispondono a come voglio che vengano creati i triangoli
            Indexes[0] = 0;
            Indexes[1] = 1; // primo  triangolo
            Indexes[2] = 2;

            Indexes[3] = 2;
            Indexes[4] = 1; // secondo tringolo
            Indexes[5] = 3;

        }

    }

    class InformationData
    {
        public int fps;
        public int second;
        public int minute;

        public string Time()
        {
            return (((minute.ToString().Length == 1) ? "0" + minute : minute.ToString()) + " : " +
                        ((second.ToString().Length == 1) ? "0" + second : second.ToString())
                        );
        }
    }
    
    [Serializable]
    class SettingsData {
        public int heightResolution = 600;
        public int widhtResolution = 800;
        public bool isFullScreen = false;
        public int selectedResolution = 0;
        public bool useJoystic = false;
        public float effectVolume = 1;
        public float musicVolume = 1;
    }

}
